package database

import (
	"JoRedis/interface/database"
	"sync"
)

// 数据存储的字典
type SyncDict struct {
	dbMap sync.Map
}

func MakeSyncDict() *SyncDict {
	return &SyncDict{}
}

func (this *SyncDict) Get(key string) (val interface{}, exists bool) {
	val, exists = this.dbMap.Load(key)
	return
}

func (this *SyncDict) Len() int {
	var len = 0
	this.dbMap.Range(func(key, value interface{}) bool {
		len++
		return true
	})
	return len
}

func (this *SyncDict) Put(key string, val interface{}) (result int) {
	_, exist := this.dbMap.Load(key)
	this.dbMap.Store(key, val)
	if exist {
		return 0
	}
	return 1
}

func (this *SyncDict) PutIfAbsent(key string, val interface{}) (result int) {
	_, exist := this.dbMap.Load(key)
	if exist {
		return 0
	}
	this.dbMap.Store(key, val)
	return 1
}

func (this *SyncDict) PutIfExists(key string, val interface{}) (result int) {
	_, exist := this.dbMap.Load(key)
	if exist {
		this.dbMap.Store(key, val)
		return 1
	}
	return 0
}

func (this *SyncDict) Remove(key string) (result int) {
	_, exist := this.dbMap.Load(key)
	this.dbMap.Delete(key)
	if exist {
		return 1
	}
	return 0
}

func (this *SyncDict) ForEach(iteratorFun database.IteratorFun) {
	this.dbMap.Range(func(key, value interface{}) bool {
		return iteratorFun(key.(string), value)
	})
}

func (this *SyncDict) Keys() []string {
	keySlc := make([]string, 0, this.Len())
	this.dbMap.Range(func(key, value interface{}) bool {
		keySlc = append(keySlc, key.(string))
		return true
	})
	return keySlc
}

func (this *SyncDict) RandomKeys(limit int) []string {
	keySlc := make([]string, limit)
	for i := 0; i < limit; i++ {
		this.dbMap.Range(func(key, value interface{}) bool {
			keySlc[i] = key.(string)
			return false
		})
	}
	return keySlc
}

func (this *SyncDict) RandomDistinctKeys(limit int) []string {
	keySlc := make([]string, limit)
	i := 0
	this.dbMap.Range(func(key, value interface{}) bool {
		keySlc[i] = key.(string)
		if i < limit {
			return true
		}
		return false
	})
	return keySlc
}

func (this *SyncDict) Clear() {
	this = MakeSyncDict()
}
